package handler

import (
	"net/http"
	"strconv"
	"time"
	
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
	"less_day/internal/model"
)

type CheckInHandler struct {
	db  *gorm.DB
	rdb *redis.Client
}

func NewCheckInHandler(db *gorm.DB, rdb *redis.Client) *CheckInHandler {
	return &CheckInHandler{db: db, rdb: rdb}
}

func (h *CheckInHandler) CreateCheckIn(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, model.APIResponse{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
		})
		return
	}

	var req model.CheckInRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, model.APIResponse{
			Code:    400,
			Message: "请求参数错误",
			Data:    nil,
		})
		return
	}

	// 检查今日是否已打卡
	today := time.Now().Format("2006-01-02")
	var existingCheckIn model.CheckInRecord
	if err := h.db.Where("user_id = ? AND DATE(check_in_date) = ?", userID, today).First(&existingCheckIn).Error; err == nil {
		c.JSON(http.StatusConflict, model.APIResponse{
			Code:    409,
			Message: "今日已打卡",
			Data:    nil,
		})
		return
	}

	// 创建打卡记录
	checkIn := model.CheckInRecord{
		UserID:         userID.(uint),
		ItemName:       req.ItemName,
		ItemCategory:   req.ItemCategory,
		ItemDescription: req.ItemDescription,
		ItemReason:     req.ItemReason,
		ItemImage:      req.ItemImage,
		CheckInDate:    time.Now(),
		CreatedAt:      time.Now(),
	}

	if err := h.db.Create(&checkIn).Error; err != nil {
		c.JSON(http.StatusInternalServerError, model.APIResponse{
			Code:    500,
			Message: "创建打卡记录失败",
			Data:    nil,
		})
		return
	}

	// 更新用户统计
	h.updateUserStats(userID.(uint))

	c.JSON(http.StatusCreated, model.APIResponse{
		Code:    201,
		Message: "打卡成功",
		Data:    checkIn,
	})
}

func (h *CheckInHandler) GetTodayCheckIn(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, model.APIResponse{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
		})
		return
	}

	today := time.Now().Format("2006-01-02")
	var checkIn model.CheckInRecord
	if err := h.db.Where("user_id = ? AND DATE(check_in_date) = ?", userID, today).First(&checkIn).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			c.JSON(http.StatusOK, model.APIResponse{
				Code:    200,
				Message: "今日未打卡",
				Data:    nil,
			})
		} else {
			c.JSON(http.StatusInternalServerError, model.APIResponse{
				Code:    500,
				Message: "查询失败",
				Data:    nil,
			})
		}
		return
	}

	c.JSON(http.StatusOK, model.APIResponse{
		Code:    200,
		Message: "获取成功",
		Data:    checkIn,
	})
}

func (h *CheckInHandler) GetCheckInList(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, model.APIResponse{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
		})
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
	offset := (page - 1) * limit

	var records []model.CheckInRecord
	var total int64

	h.db.Model(&model.CheckInRecord{}).Where("user_id = ?", userID).Count(&total)
	
	if err := h.db.Where("user_id = ?", userID).
		Order("check_in_date DESC").
		Limit(limit).
		Offset(offset).
		Find(&records).Error; err != nil {
		c.JSON(http.StatusInternalServerError, model.APIResponse{
			Code:    500,
			Message: "查询失败",
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, model.APIResponse{
		Code:    200,
		Message: "获取成功",
		Data: gin.H{
			"list":  records,
			"total": total,
			"page":  page,
			"limit": limit,
		},
	})
}

func (h *CheckInHandler) UpdateCheckIn(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, model.APIResponse{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
		})
		return
	}

	id, _ := strconv.Atoi(c.Param("id"))
	var checkIn model.CheckInRecord
	if err := h.db.Where("id = ? AND user_id = ?", id, userID).First(&checkIn).Error; err != nil {
		c.JSON(http.StatusNotFound, model.APIResponse{
			Code:    404,
			Message: "打卡记录不存在",
			Data:    nil,
		})
		return
	}

	var req model.UpdateCheckInRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, model.APIResponse{
			Code:    400,
			Message: "请求参数错误",
			Data:    nil,
		})
		return
	}

	updates := map[string]interface{}{}
	if req.ItemName != "" {
		updates["item_name"] = req.ItemName
	}
	if req.ItemCategory != "" {
		updates["item_category"] = req.ItemCategory
	}
	if req.ItemDescription != "" {
		updates["item_description"] = req.ItemDescription
	}
	if req.ItemReason != "" {
		updates["item_reason"] = req.ItemReason
	}
	if req.ItemImage != "" {
		updates["item_image"] = req.ItemImage
	}

	if err := h.db.Model(&checkIn).Updates(updates).Error; err != nil {
		c.JSON(http.StatusInternalServerError, model.APIResponse{
			Code:    500,
			Message: "更新失败",
			Data:    nil,
		})
		return
	}

	c.JSON(http.StatusOK, model.APIResponse{
		Code:    200,
		Message: "更新成功",
		Data:    checkIn,
	})
}

func (h *CheckInHandler) DeleteCheckIn(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, model.APIResponse{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
		})
		return
	}

	id, _ := strconv.Atoi(c.Param("id"))
	if err := h.db.Where("id = ? AND user_id = ?", id, userID).Delete(&model.CheckInRecord{}).Error; err != nil {
		c.JSON(http.StatusInternalServerError, model.APIResponse{
			Code:    500,
			Message: "删除失败",
			Data:    nil,
		})
		return
	}

	// 更新用户统计
	h.updateUserStats(userID.(uint))

	c.JSON(http.StatusOK, model.APIResponse{
		Code:    200,
		Message: "删除成功",
		Data:    nil,
	})
}

func (h *CheckInHandler) updateUserStats(userID uint) {
	// 计算总打卡天数
	var totalDays int64
	h.db.Model(&model.CheckInRecord{}).Where("user_id = ?", userID).Count(&totalDays)

	// 计算总物品数量
	var totalItems int64
	h.db.Model(&model.CheckInRecord{}).Where("user_id = ?", userID).Count(&totalItems)

	// 计算连续打卡天数
	currentStreak := h.calculateStreak(userID)

	// 获取最长连续天数
	var user model.User
	h.db.First(&user, userID)
	longestStreak := user.LongestStreak
	if currentStreak > longestStreak {
		longestStreak = currentStreak
	}

	// 更新用户统计
	h.db.Model(&model.User{}).Where("id = ?", userID).Updates(map[string]interface{}{
		"total_days":     totalDays,
		"total_items":    totalItems,
		"current_streak": currentStreak,
		"longest_streak": longestStreak,
	})
}

func (h *CheckInHandler) calculateStreak(userID uint) int {
	var records []model.CheckInRecord
	h.db.Where("user_id = ?", userID).
		Order("check_in_date DESC").
		Find(&records)

	if len(records) == 0 {
		return 0
	}

	streak := 0
	currentDate := time.Now().Truncate(24 * time.Hour)

	for _, record := range records {
		recordDate := record.CheckInDate.Truncate(24 * time.Hour)
		diff := currentDate.Sub(recordDate).Hours() / 24

		if diff == float64(streak) {
			streak++
		} else {
			break
		}
	}

	return streak
}